﻿using ANX.Framework;
using ANX.Framework.Graphics;
using ANXGame.Model;
using ANXGame.Model.Helpers;
using Core.Model.Blocks;
using Core.Model.Chunks;
using Core.Model.Types;
using Core.View.Builders;

namespace ANXGame.View.Builders
{
    public class XnaChunkBuilder : ChunkBuilder
    {
        public BlockVertex[] vertexList = new BlockVertex[8 * Chunk.BlockCount];
        public short[] indexList = new short[36 * Chunk.BlockCount];

        private GraphicsDevice Graphics;

        private int VertexPosition;
        private int IndexPosition;

        public XnaChunkBuilder(GraphicsDevice graphics)
        {
            Graphics = graphics;
        }

        #region Overriden methods

        public override Chunk CreateChunk(VectorIndex index)
        {
            return new XnaChunk(index);
        }

        protected override void BeforeChunkBuild(Chunk chunk)
        {
            VertexPosition = 0;
            IndexPosition = 0;
        }

        protected override void AddVertex(Chunk chunk, BlockFaceDirection faceDir, BlockType blockType, Vector3I blockPosition, Vector3I chunkRelativePosition, Vector3F vertexAdd, Vector3F normal, Vector2F uv1, byte sunLight, System.Drawing.Color localLight)
        {
            base.AddVertex(chunk, faceDir, blockType, blockPosition, chunkRelativePosition, vertexAdd, normal, uv1, sunLight, localLight);

            if (faceDir != BlockFaceDirection.YIncreasing)
            {
                sunLight -= 2;

                if (sunLight < 0)
                {
                    sunLight = 0;
                }
            }

            vertexList[VertexPosition] = new BlockVertex(
                new Vector4(chunkRelativePosition.X + vertexAdd.X, chunkRelativePosition.Y + vertexAdd.Y, chunkRelativePosition.Z + vertexAdd.Z, sunLight),
                TypeCompatibleHelper.ConvertFromVector2F(uv1));

            VertexPosition++;

            //VertexStream.WriteByte((byte)(chunkRelativePosition.X + vertexAdd.X));
            //VertexStream.WriteByte((byte)(chunkRelativePosition.Y + vertexAdd.Y));
            //VertexStream.WriteByte((byte)(chunkRelativePosition.Z + vertexAdd.Z));
            //VertexStream.WriteByte(sunLight);

            //VertexStream.Write(new Vector4(255.0f, 0.0f, 0.0f, 1.0f));
            //VertexStream.Write(uv1);
        }

        protected override void AddIndex(Chunk chunk, BlockType blockType, short i1, short i2, short i3, short i4, short i5, short i6)
        {
            base.AddIndex(chunk, blockType, i1, i2, i3, i4, i5, i6);

            int vertexCount = VertexPosition - 4;

            indexList[IndexPosition]=(short)(vertexCount + i1);
            IndexPosition++;

            indexList[IndexPosition]=(short)(vertexCount + i2);
            IndexPosition++;

            indexList[IndexPosition]=(short)(vertexCount + i3);
            IndexPosition++;

            indexList[IndexPosition]=(short)(vertexCount + i4);
            IndexPosition++;

            indexList[IndexPosition]=(short)(vertexCount + i5);
            IndexPosition++;

            indexList[IndexPosition]=(short)(vertexCount + i6);
            IndexPosition++;
        }

        protected override void AfterChunkBuild(Chunk chunk)
        {
            // Before create buffer

            int vertexCount = VertexPosition;
            int indexCount = IndexPosition;

            XnaChunk xnaChunk = (XnaChunk)chunk;

            if (xnaChunk.VertexBuffer != null)
            {
                xnaChunk.VertexBuffer.Dispose();
                xnaChunk.VertexBuffer = null;
            }

            xnaChunk.VertexBuffer = new VertexBuffer(Graphics, typeof(BlockVertex), vertexCount, BufferUsage.WriteOnly);
            xnaChunk.VertexBuffer.SetData(vertexList, 0, vertexCount);

            if (xnaChunk.IndexBuffer != null)
            {
                xnaChunk.IndexBuffer.Dispose();
                xnaChunk.IndexBuffer = null;
            }

            xnaChunk.IndexBuffer = new IndexBuffer(Graphics, typeof(short), indexCount, BufferUsage.WriteOnly);
            xnaChunk.IndexBuffer.SetData(indexList, 0, indexCount);

            chunk.VertexCount = vertexCount;
            chunk.IndexCount = indexCount;
            chunk.PrimitivesCount = indexCount/3;

            chunk.IsReady = true;
        }

        #endregion
    }
}
